/* eslint-disable max-len */
import React, {
  useRef, Suspense, useState, useEffect,
} from 'react';
import { observer } from 'mobx-react-lite';
import {
  Page, Header, Breadcrumb, Content, HeaderButtons, useFormatMessage,
} from '@choerodon/master';
import { Modal as ModalInstance, useModal } from 'choerodon-ui/pro';
import { useSessionStorageState } from 'ahooks';
import { useHistory, useLocation } from 'react-router';
import { OverflowWrap } from '@choerodon/components';
import { mount, get } from '@choerodon/inject';
import queryString from 'query-string';
import PipelineTree from './components/PipelineTree';
import PipelineFlow from './components/PipelineFlow';
import DragBar from '@/components/drag-bar';
import {
  handleModal,
} from './components/time-trigger';
import RecordDetail from './components/record-detail';
import EmptyPage from '@/components/empty-page';
import { mapping } from '../app-pipeline-edit/components/pipeline-advanced-config/stores/pipelineAdvancedConfigDataSet';
import { usePipelineManageStore } from './stores';
import VariableSettings from './components/variable-settings';
import AuditModal from './components/audit-modal';
import GitlabRunner from './components/gitlab-runner';
import { usePipelineCreateModal, handleModalOpen } from './components/pipeline-create-modal';
import { PIPELINE_CREATE_LOCALSTORAGE_IDENTIFY } from '@/routes/app-pipeline/stores/CONSTANTS';

import './index.less';

const recordDetailKey = ModalInstance.key();
const settingsKey = ModalInstance.key();
const auditKey = ModalInstance.key();
const runnerKey = ModalInstance.key();
const modalStyle = {
  width: 380,
};
const settingsModalStyle = {
  width: 740,
};

const PipelineManage = observer(() => {
  const {
    intl: { formatMessage },
    intlPrefix,
    prefixCls,
    permissions,
    mainStore,
    editBlockStore,
    detailStore,
    treeDs,
    projectId,
    appPipelineFlowModel,
    hasCtyunTree,
  } = usePipelineManageStore();

  const Modal = useModal();

  const format = useFormatMessage('c7ncd.pipelineManage');
  const [, setPipelineCreateData] = useSessionStorageState(PIPELINE_CREATE_LOCALSTORAGE_IDENTIFY);

  const globalCiDisplay = get('configuration.devops-routes-app-pipeline:globalCiDisplay');

  const localCiDisplay = get('configuration.devops-routes-app-pipeline:localCiDisplay');

  const [globalDisplay, setGlobalDisplay] = useState(true);

  const [localDisplay, setLocalDisplay] = useState(true);

  const { getSelectedMenu } = mainStore;

  const {
    getMainData, loadData, getLoading,
  } = editBlockStore;

  const {
    appServiceId,
  } = getMainData || {};

  const {
    parentId,
  } = getSelectedMenu || {};

  useEffect(() => {
    handleSetGlobalDisplay();
    handleSetLocalDisplay();
  }, [parentId, appServiceId]);

  async function handleSetGlobalDisplay() {
    if (parentId && String(globalCiDisplay) !== 'undefined') {
      const result = await globalCiDisplay(projectId, parentId);
      setGlobalDisplay(result);
    }
  }

  async function handleSetLocalDisplay() {
    if (appServiceId && String(localCiDisplay) !== 'undefined') {
      const result = await localCiDisplay(projectId, appServiceId);
      setLocalDisplay(result);
    }
  }

  const {
    loadDetailData, getDetailData, getDetailLoading,
  } = detailStore;

  const history = useHistory();
  const {
    pathname,
    search,
  } = useLocation();

  // const handleModalOpen = usePipelineCreateModal();

  const rootRef = useRef(null);

  const handleRefresh = async () => {
    if (hasCtyunTree) {
      mainStore.setCtyunFresh();
      mainStore.setCtyunSearchValue('');
      return;
    }
    mainStore.setLoadedKeys([]);
    mainStore.setTreeDataPage(1);
    await treeDs.query();
    const { id } = getMainData;
    // const { parentId } = getSelectedMenu;
    const { devopsPipelineRecordRelId, id: detailId } = getDetailData;
    if (!parentId) {
      id && loadData(projectId, id);
    } else {
      detailId && loadDetailData(projectId, detailId);
    }
  };

  function handleModify() {
    const config = get('configuration.devops-routes-pipeline-manage:modifySavedData');
    const {
      id,
      appServiceCode,
      appServiceName,
      name,
      objectVersionNumber,
    } = getMainData || {};
    let data = {};
    if (config) {
      data = config(getMainData);
    }
    setPipelineCreateData({
      pipelineId: id,
      pipelineName: name,
      objectVersionNumber,
      appService: {
        appServiceCode, appServiceId, appServiceName,
      },
      [mapping.CIRunnerImage.name]: getMainData?.[mapping.CIRunnerImage.name],
      [mapping.versionName.name]: getMainData?.[mapping.versionName.name],
      ...data,
    });
    let url;
    if (search.indexOf('pipelineId') !== -1) {
      const searchObj = queryString.parse(search);
      delete searchObj.pipelineId;
      url = queryString.stringify(searchObj);
    } else {
      url = search;
    }
    history.push({
      search: url,
      pathname: `${pathname}/edit/edit/${id}`,
    });
  }

  function openRecordDetail() {
    const { devopsPipelineRecordRelId } = getSelectedMenu;
    const { devopsPipelineRecordRelId: detailDevopsPipelineRecordRelId, viewId } = getDetailData;
    const newDevopsPipelineRecordRelId = devopsPipelineRecordRelId || detailDevopsPipelineRecordRelId;
    Modal.open({
      key: recordDetailKey,
      style: modalStyle,
      title: (
        <span className={`${prefixCls}-detail-modal-title`}>
          流水线记录“
          <OverflowWrap width="100px">
            {`#${viewId}`}
          </OverflowWrap>
          ”的详情
        </span>
      ),
      children: <RecordDetail
        pipelineRecordId={newDevopsPipelineRecordRelId}
        intlPrefix={intlPrefix}
        refresh={handleRefresh}
        store={mainStore}
      />,
      drawer: true,
      okCancel: false,
      okText: formatMessage({ id: 'close' }),
    });
  }

  async function changeRecordExecute(type) {
    const { gitlabProjectId, gitlabPipelineId, devopsPipelineRecordRelId } = getSelectedMenu;
    const {
      gitlabProjectId: detailGitlabProjectId,
      gitlabPipelineId: detailGitlabPipelineId,
      devopsPipelineRecordRelId: detailDevopsPipelineRecordRelId,
    } = getDetailData;
    const res = await mainStore.changeRecordExecute({
      projectId,
      gitlabProjectId: gitlabProjectId || detailGitlabProjectId,
      recordId: gitlabPipelineId || detailGitlabPipelineId,
      type,
      devopsPipelineRecordRelId: devopsPipelineRecordRelId || detailDevopsPipelineRecordRelId,
    });
    if (res) {
      handleRefresh();
    }
  }

  const openAuditModal = (incomingData, incomingRefresh) => {
    const { devopsCdPipelineDeatilVO } = getSelectedMenu;
    const {
      cdRecordId,
      devopsCdPipelineDeatilVO: detailDevopsCdPipelineDeatilVO,
      pipelineName,
    } = getDetailData;

    let checkData = devopsCdPipelineDeatilVO || detailDevopsCdPipelineDeatilVO;
    if (incomingData) {
      checkData = incomingData.devopsCdPipelineDeatilVO;
    }

    Modal.open({
      key: auditKey,
      title: formatMessage({ id: `${intlPrefix}.execute.audit` }),
      children: <AuditModal
        cdRecordId={incomingData?.cdRecordId || cdRecordId}
        name={incomingData?.pipelineName || pipelineName}
        mainStore={mainStore}
        onClose={handleRefresh}
        checkData={checkData}
        incomingRefresh={incomingRefresh}
      />,
      movable: false,
    });
  };

  function openSettingsModal(type) {
    const {
      appServiceName, id,
    } = getSelectedMenu;
    Modal.open({
      key: settingsKey,
      style: settingsModalStyle,
      title: formatMessage({ id: `${intlPrefix}.settings.${type}` }),
      children: <VariableSettings
        intlPrefix={intlPrefix}
        appServiceId={type === 'global' ? null : appServiceId}
        appServiceName={type === 'global' ? null : appServiceName}
        store={mainStore}
        refresh={handleRefresh}
        appPipelineFlowModel={appPipelineFlowModel}
        groupId={parentId}
        pipelineId={id}
      />,
      drawer: true,
      okText: formatMessage({ id: 'boot.save' }),
    });
  }

  function openRunnerModal() {
    Modal.open({
      key: runnerKey,
      style: settingsModalStyle,
      // title: formatMessage({ id: `${intlPrefix}.gitlab.runner` }),
      title: '注册 Gitlab Group Runner 指引',
      children: <GitlabRunner />,
      drawer: true,
      okCancel: false,
      okText: formatMessage({ id: 'close' }),
    });
  }

  function getHeaderButtons() {
    if (appPipelineFlowModel === 'tree' && getLoading) {
      return [];
    } if (appPipelineFlowModel === 'simple' && getLoading && !parentId) {
      return [];
    } if (appPipelineFlowModel === 'simple' && getDetailLoading && parentId) {
      return [];
    }
    const {
      status, devopsCdPipelineDeatilVO, type,
    } = getSelectedMenu;
    // type: 为树模式时候判断是流水线还是group

    const {
      status: detailStatus,
      devopsCdPipelineDeatilVO: detailDevopsCdPipelineDeatilVO,
    } = getDetailData;
    let buttons = [{
      permissions: ['choerodon.code.project.develop.ci-pipeline.ps.createPro'],
      name: format({ id: 'CreatePipeline' }),
      icon: 'playlist_add',
      handler: handleModalOpen,
    }];
    let groupBtnItems = [
      {
        name: format({ id: 'GitLabRunner' }),
        service: ['choerodon.code.project.develop.ci-pipeline.ps.runner'],
        handler: openRunnerModal,
      },
    ];
    const modifyBtnConfig = {
      permissions: ['choerodon.code.project.develop.ci-pipeline.ps.update'],
      name: format({ id: 'Modify' }),
      icon: 'edit-o',
      handler: handleModify,
    };
    const CIVariableBtnConfig = {
      permissions: ['choerodon.code.project.develop.ci-pipeline.ps.variable.app'],
      name: format({ id: 'CIVariable' }),
      icon: '',
      display: localDisplay,
      handler: () => openSettingsModal('local'),
    };
    if (appPipelineFlowModel === 'simple' && treeDs.length && treeDs.status === 'ready') {
      if (!parentId) {
        buttons.push(modifyBtnConfig);
        groupBtnItems.push(CIVariableBtnConfig);
      } else {
        const newStatus = status || detailStatus;
        const newDevopsCdPipelineDeatilVO = devopsCdPipelineDeatilVO || detailDevopsCdPipelineDeatilVO;
        groupBtnItems = [
          ...groupBtnItems,
          {
            name: format({ id: 'RecordDetails' }),
            icon: 'find_in_page-o',
            handler: openRecordDetail,
          }, {
            permissions: ['choerodon.code.project.develop.ci-pipeline.ps.cancel'],
            name: format({ id: 'CancelExecution' }),
            icon: 'power_settings_new',
            handler: () => changeRecordExecute('cancel'),
            display: newStatus === 'pending' || newStatus === 'running',
          }, {
            permissions: ['choerodon.code.project.develop.ci-pipeline.ps.retry'],
            name: format({ id: 'Retry' }),
            icon: 'refresh',
            handler: () => changeRecordExecute('retry'),
            display: newStatus === 'failed' || newStatus === 'canceled',
          }, {
            permissions: ['choerodon.code.project.develop.ci-pipeline.ps.audit'],
            name: formatMessage({ id: `${intlPrefix}.execute.audit` }),
            icon: 'authorize',
            handler: () => { openAuditModal(); },
            display: newStatus === 'not_audit' && newDevopsCdPipelineDeatilVO && newDevopsCdPipelineDeatilVO.execute,
          },
        ];
      }
    }
    if (appPipelineFlowModel === 'tree' && type === 'pipeline') {
      buttons.push(modifyBtnConfig);
      groupBtnItems.push(CIVariableBtnConfig);
    }
    if (appPipelineFlowModel === 'simple' || (appPipelineFlowModel === 'tree' && type === 'pipeline')) {
      buttons.push({
        icon: 'settings-o',
        permissions: ['choerodon.code.project.develop.ci-pipeline.ps.timeTrigger'],
        name: format({ id: 'timeTrigger' }),
        display: mainStore.getSelectedMenu && JSON.stringify(mainStore.getSelectedMenu) !== '{}',
        handler: () => {
          handleModal(appServiceId);
        },
      });
    }
    buttons = [
      ...buttons,
      {
        permissions: ['choerodon.code.project.develop.ci-pipeline.ps.variable.project'],
        name: format({ id: 'GlobalCI' }),
        icon: 'settings-o',
        handler: () => openSettingsModal('global'),
        display: globalDisplay,
      },
      {
        name: format({ id: 'MoreActions' }),
        groupBtnItems,
      },
      {
        icon: 'refresh',
        handler: handleRefresh,
        display: true,
      },
    ];
    buttons.push();

    return buttons;
  }

  const getEmptyPage = () => (appPipelineFlowModel === 'simple'
    ? (
      <div className={`${prefixCls}-wrap`}>
        <Suspense fallback={<span />}>
          <EmptyPage
            title={formatMessage({ id: 'empty.title.pipeline' })}
            describe={formatMessage({ id: 'empty.tips.pipeline.owner' })}
            btnText={formatMessage({ id: `${intlPrefix}.create` })}
            onClick={handleModalOpen}
            access
          />
        </Suspense>
      </div>
    ) : (
      <div className={`${prefixCls}-wrap`}>
        <Suspense fallback={<span />}>
          {mount('configuration.devops-routes-pipeline-manage:empty-pipeline', { prefixCls, handleModalOpen })}
        </Suspense>
      </div>
    ));

  const isEmpty = hasCtyunTree ? mainStore.getCtyunEmpty : !treeDs.length && treeDs.status === 'ready' && !mainStore.getSearchValue;
  return (
    <Page className="pipelineManage_page">
      <Header title="流水线">
        <HeaderButtons items={getHeaderButtons()} showClassName={false} />
      </Header>
      <Breadcrumb />
      <Content className={`${prefixCls}-content`}>
        {isEmpty ? getEmptyPage() : (
          <div
            ref={rootRef}
            className={`${prefixCls}-wrap`}
          >
            <DragBar
              parentRef={rootRef}
              store={mainStore}
            />
            <PipelineTree handleRefresh={handleRefresh} />
            <div className={`${prefixCls}-main ${prefixCls}-animate`}>
              {mainStore.getUnrelatedFlag === 'true' ? <span>123</span> : (
                <PipelineFlow
                  handleRefresh={handleRefresh}
                  openAuditModal={openAuditModal}
                />
              )}

            </div>
          </div>
        )}
      </Content>
    </Page>
  );
});

export default PipelineManage;
